/**
* Copyright (c) 2024 Huawei Technologies Co., Ltd.
* This file is a part of the CANN Open Software.
* Licensed under CANN Open Software License Agreement Version 1.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/

/*!
* \file matmul_unit_flag_params.h
* \brief
*/
#ifndef IMPL_MATMUL_MODULES_MATMUL_L0C_BUFFER_H
#define IMPL_MATMUL_MODULES_MATMUL_L0C_BUFFER_H

#include "../matmul_module.h"
#include "../matmul_param.h"

namespace matmul {

enum class UNIT_FLAG_CTRL : uint8_t {
    DISABLE,
    RESERVED,
    CHECK,
    SET,
};

template <typename ENTITY, bool EN_UNIT_FLAG>
class MatmulL0CBuffer
{
public:
    template <typename L0cT>
    __aicore__ inline void InitL0CBuffer(uint32_t lenFactor = 1)
    {
        MATMUL_PARAM_VAR.tpipe_->InitBuffer(MATMUL_PARAM_VAR.CO1_, lenFactor * MATMUL_PARAM_VAR.baseMN_ * sizeof(L0cT));
    }

    template <typename L0cT>
    __aicore__ inline LocalTensor<L0cT> LoadL0CTensor() 
    {
        return MATMUL_PARAM_VAR.CO1_.template Get<L0cT>();
    }

    template <typename L0cT>
    __aicore__ inline LocalTensor<L0cT> AllocL0CLocalTensor()
    {
        LocalTensor<L0cT> co1Local;
        co1Local = MATMUL_PARAM_VAR.cMatrix_;
        return co1Local;
    }

    template <typename L0cT>
    __aicore__ inline void FreeL0CLocalTensor(LocalTensor<L0cT> &co1Local)
    {}

    __aicore__ inline void ResetL0CEventStatus()
    {
        event_t eventIDFixToM = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::FIX_M));
        SetFlag<HardEvent::FIX_M>(eventIDFixToM);
        WaitFlag<HardEvent::FIX_M>(eventIDFixToM);
    }

    __aicore__ inline bool IsL0CLastIter(int l0CIterNum) const
    {
        return l0CIterNum == MATMUL_CONST_PARAM_VAR.kIter_ - 1;
    }

    __aicore__ inline uint8_t GetMmadUnitFlagCtrl(bool isFinalCompute) const
    {
        return static_cast<uint8_t>(isFinalCompute ? UNIT_FLAG_CTRL::SET : UNIT_FLAG_CTRL::CHECK);
    }

    template<typename FIX_PIPE_PARAMS>
    __aicore__ inline void SetFixpipeUnitFlag(FIX_PIPE_PARAMS& fixpipeParams)
    {
        fixpipeParams.unitFlag = FIX_PIPE_UNIT_FLAG;
    }

private:
    constexpr static uint8_t FIX_PIPE_UNIT_FLAG = 3;
};

template <typename ENTITY>
class MatmulL0CBuffer<ENTITY, false>
{
public:
    template <typename L0cT>
    __aicore__ inline void InitL0CBuffer(uint32_t lenFactor = 1)
    {
        if (MATMUL_PARAM_VAR.tiling_->dbL0C == 2) {
            MATMUL_PARAM_VAR.tpipe_->InitBuffer(
                MATMUL_PARAM_VAR.CO1_, 2, lenFactor * MATMUL_PARAM_VAR.baseMN_ * sizeof(L0cT));
        } else {
            MATMUL_PARAM_VAR.tpipe_->InitBuffer(
                MATMUL_PARAM_VAR.CO1_, 1, lenFactor * MATMUL_PARAM_VAR.baseMN_ * sizeof(L0cT));
        }
    }

    template <typename L0cT>
    __aicore__ inline LocalTensor<L0cT> LoadL0CTensor()
    {
        return MATMUL_PARAM_VAR.CO1_.template AllocTensor<L0cT>();
    }

    template <typename L0cT>
    __aicore__ inline LocalTensor<L0cT> AllocL0CLocalTensor()
    {
        LocalTensor<L0cT> co1Local;
        MATMUL_PARAM_VAR.CO1_.EnQue(MATMUL_PARAM_VAR.cMatrix_);
        co1Local = MATMUL_PARAM_VAR.CO1_.template DeQue<L0cT>();
        return co1Local;
    }

    template <typename L0cT>
    __aicore__ inline void FreeL0CLocalTensor(LocalTensor<L0cT> &co1Local)
    {
        MATMUL_PARAM_VAR.CO1_.FreeTensor(co1Local);
    }

    __aicore__ inline void ResetL0CEventStatus()
    {
        MATMUL_PARAM_VAR.CO1_.FreeAllEvent();
    }

    __aicore__ inline bool IsL0CLastIter(int l0CIterNum) const
    {
        return false;
    }

    __aicore__ inline uint8_t GetMmadUnitFlagCtrl(bool isFinalCompute) const
    {
        return static_cast<uint8_t>(UNIT_FLAG_CTRL::DISABLE);
    }

    template<typename FIX_PIPE_PARAMS>
    __aicore__ inline void SetFixpipeUnitFlag(FIX_PIPE_PARAMS& fixpipeParams)
    {}
};

}
#endif // _MATMUL_L0C_BUFFER_H_